using Basis;
using DG.Tweening;
using System;
using UnityEngine;
using UnityEngine.EventSystems;
//using UnityEngine.Rendering.Universal;

namespace NL.Advanced
{
    /// <summary>
    /// 相机设置结构体
    /// </summary>
    [Serializable]
    public struct GameCameraSetting
    {
        /// <summary>
        /// 相机位置
        /// </summary>
        [Header("相机位置，w>0时为有效数据(Camera_Home.Position)")]
        public Vector4 Position;

        /// <summary>
        /// 相机视野（水平转向角度、俯仰角度、视野宽度(FOV)）
        /// </summary>
        [Header("相机视野，w>0时为有效数据(Camera_Home.Main_Camera.Rotation)")]
        public Vector4 ViewAngle;

        [Header("视野宽度(fieldOfView)，大于0时有效")]
        public float FOV;

        [Header("摄像机高度限制，大于0时有效")]
        public float HighMin;
        public float HighMax;

        [Header("摄像机高度默认值，大于0时有效")]
        public float HighDefault;
        [Header("聚焦操作时，摄像机高度，大于0时有效")]
        public float HighFocus;

        [Header("使用此设置时，摄像变化曲线模式")]
        public Ease EaseType;

        [Header("使用此设置时，摄像变化时长s")]
        public float duration;
    }

    public partial class CameraController : CameraBase
    {

        public enum Type
        {
            /// <summary>
            /// 正常
            /// </summary>
            Normal,

            /// <summary>
            /// 大富翁玩法
            /// </summary>
            Monopoly,
        }

        private Type _type = Type.Normal;

        public static CameraController INSTANCE;

        public bool OpenSelfControl = false;

        public Transform DefaultFocus;




        //public float ZoomStep = 1f; //与CameraZoomCorrectly功能一样












        public Camera GameCamera;

        // [Header("有效区..")]
        public IBoundOwner BoundOwner;
        GameObject BoundParentMapObj;


        //public Rect BoundRect=>new Rect()
        //{ 
        //     center= BoundOwner==null? Vector2.zero:BoundOwner.transform.position+BoundOwner.Bound.center,
        //      height= BoundOwner == null ?1000:BoundOwner.Bound.
        //}


        [Header("镜头压黑")]
        [SerializeField] private GameObject _Black;




        // Start is called before the first frame update
        protected override void Awake()
        {
            base.Awake();
            INSTANCE = this;
            if (MainCamera == null) MainCamera = GetComponentInChildren<Camera>();

            //初始化参数
            //读取 配置文件.
            if (SYS.ConfigOf("camera_drag_correctly").AsFloat > float.MinValue)
                CameraDragCorrectly = SYS.ConfigOf("camera_drag_correctly").AsFloat;
            if (SYS.ConfigOf("camera_zoom_correctly").AsFloat > float.MinValue)
                CameraZoomCorrectly = SYS.ConfigOf("camera_zoom_correctly").AsFloat;


            if (SYS.ConfigOf("camera_high_default").AsFloat > float.MinValue)
                Config.HighDefault = SYS.ConfigOf("camera_high_default").AsFloat;


            if (SYS.ConfigOf("camera_high_focus").AsFloat > float.MinValue)
                Config.HighFocus = SYS.ConfigOf("camera_high_focus").AsFloat;

            if (SYS.ConfigOf("camera_high_min").AsFloat > float.MinValue)
                Config.HighMin = SYS.ConfigOf("camera_high_min").AsFloat;
            if (SYS.ConfigOf("camera_high_max").AsFloat > float.MinValue)
                Config.HighMax = SYS.ConfigOf("camera_high_max").AsFloat;


            if (SYS.ConfigOf("camera_focus_speed").AsFloat > float.MinValue)
                Config.FocusSpeed = SYS.ConfigOf("camera_focus_speed").AsFloat;


            //if (SYS.ConfigOf("camera_yaw").AsFloat > float.MinValue)
            //    CameraYaw = SYS.ConfigOf("camera_yaw").AsFloat;
            //if (SYS.ConfigOf("camera_pitch").AsFloat > float.MinValue)
            //    CameraPitch = SYS.ConfigOf("camera_pitch").AsFloat;
            //if (SYS.ConfigOf("camera_fov").AsFloat > 0)
            //    CameraFOV = SYS.ConfigOf("camera_fov").AsFloat;




            DefaultCameraSetting.ViewAngle.x = Config.Pitch;
            DefaultCameraSetting.ViewAngle.y = Config.Yaw;
            DefaultCameraSetting.ViewAngle.z = Config.FOV;
            DefaultCameraSetting.ViewAngle.w = 1;

            DefaultCameraSetting.FOV = Config.FOV;

            DefaultCameraSetting.HighMin = Config.HighMin;
            DefaultCameraSetting.HighMax = Config.HighMax;



            Invoke("_DefaultFocus", 1);
        }

        //public Vector4 Vec_CameraHightDataDefault = Vector4.zero;
        //Vector4 Vec_CameraHightData = Vector4.zero;

        GameCameraSetting DefaultCameraSetting = new GameCameraSetting();



        //public CameraController SetCameraHightData(float min, float max, float deft, float focus)
        //{
        //    Vec_CameraHightData.x = min;
        //    Vec_CameraHightData.y = max;
        //    Vec_CameraHightData.z = deft;
        //    Vec_CameraHightData.w = focus;

        //    transform.position = new Vector3(transform.position.x, Vec_CameraHightData.y, transform.position.z);
        //    return this;
        //}

        //public CameraController ResetCameraHightDataDefault() 
        //{
        //    if (Vec_CameraHightData != Vec_CameraHightDataDefault)
        //    {
        //        Vec_CameraHightData = Vec_CameraHightDataDefault;

        //        transform.position = new Vector3(transform.position.x, Vec_CameraHightData.y, transform.position.z);
        //    }
        //    return this;
        //}

        public void SetCameraPos(Vector3 pos)
        {
            transform.position = pos;
        }


        public void SetCameraHighRange(float min, float max)
        {
            Config.HighMin = min;
            Config.HighMax = max;
        }

        void _DefaultFocus()
        {
            if (DefaultFocus != null)
                LookAt(DefaultFocus);
        }
        bool _IsMouseDown;
        protected override void Update()
        {
            if (PostionSyncing && _OnPostionSync != null)
            {
                transform.position = _OnPostionSync.Invoke();
            }

            if (OpenSelfControl)
            {
                _IsMouseDown = Input.GetMouseButton(0);

                if (_IsMouseDown)
                {
                    var x = Input.GetAxis("Mouse X");
                    var y = Input.GetAxis("Mouse Y");

                    MoveByScreent(new Vector2(x, y));
                }

                var dd = Input.GetAxis("Mouse ScrollWheel") * 10 * CameraZoomCorrectly;
                var focus = Input.mousePosition;
                if (Mathf.Abs(dd) > 0.01f)
                {
                    Zoom(dd, focus);
                }

            }



        }



        //bool _IsViewOutBound()
        //{


        //    if (BoundOwner == null) return false;

        //    foreach(var vb in ViewBoundCorners)
        //    {
        //        Vector3 pos = BoundOwner.transform.InverseTransformPoint(vb.transform.position);
        //        if (!BoundOwner.Bound.Contains(pos))
        //            return true;
        //    }

        //    return false;
        //}









        //protected override void OnDrawGizmos()
        //{
        //    base.OnDrawGizmos();
        //    //Gizmos.matrix = _MainCamer.transform.localToWorldMatrix;
        //    //Gizmos.DrawFrustum(_MainCamer.transform.position, _MainCamer.fieldOfView, 100, 1, _MainCamer.aspect);

        //    //Gizmos.d
        //    if (BoundParentMapObj == null)
        //    {
        //        return;
        //    }
        //    if (BoundOwner == null)
        //        return;
        //    if (BoundOwner.Bound == null)
        //        return;

        //    if (BoundOwner.transform != null && BoundOwner.transform.gameObject.activeInHierarchy)
        //    {
        //        Gizmos.color = Color.red;
        //        Gizmos.DrawWireCube(BoundOwner.transform.position + BoundOwner.Bound.center, BoundOwner.Bound.size);
        //    }
        //}







        /// <summary>
        /// 
        /// </summary>
        /// <param name="offset">希望偏移得量,针对屏幕百分比</param>
        public static void LOOK_OFFSET(Vector2 offset)
        {
            INSTANCE?.LookOffset(offset);
        }

        /// <summary>
        /// 聚焦到（观察）一个位置
        /// </summary>
        /// <param name="where">位置</param>
        /// <param name="camerahigh">摄像机高度（从多高的位置观测）</param>
        /// <param name="speed">相机移动速度</param>
        /// <param name="suitforbound">视场适应物体的bound（需观测物体有bound）</param>
        /// <summary>


        public void LookAt(Transform where, bool focusing)
        {
            _DoLookAt(where,
                focusing ? Config.HighFocus : Config.HighDefault,
                Config.FocusSpeed,
                true, 0);

        }



        public void LookAtForBound(Transform where, float boundzoom)
        {
            _DoLookAt(where,
                    transform.position.y,
                    Config.FocusSpeed, true, boundzoom);

        }



















        public static void ZOOM(float delt, Vector2? foucs)
        {
            INSTANCE?.Zoom(delt, foucs);
        }

        //protected void CancelDragDelay(Vector2 speed_screen)
        //{
        //    _Draging = false;
        //}
        public static void MOVE_BY_SCRRENSPEED(Vector2 speed)
        {
            INSTANCE?.MoveBySpeed(speed);
        }


        //protected bool _Draging = false;




        //private void LateUpdate()
        //{
        //    if (!_HasNewPosForBoundCheck) return;

        //    _HasNewPosForBoundCheck = false;

        //    if (_IsInBound())
        //        _LastSafePos = transform.position;
        //    else
        //        transform.position= _LastSafePos;

        //}












        public static void MOVE_BY_SCRRENPOINT(Vector2 delt)
        {

            INSTANCE?.MoveByScreent(delt);

        }

        //public static void LOOK_AT(Transform where,   float camerahigh = 0)
        //{
        //    INSTANCE?.LookAt(where, camerahigh);
        //}
        public static void LOOK_AT(Transform where, float camerahigh = 0, float pass = 0f, bool suitforbound = false)
        {
            INSTANCE?.LookAt(where, camerahigh, pass, suitforbound);
        }







        public static void MOVE(Vector3 pos)
        {
            INSTANCE.transform.Translate(pos);
        }

        /// <summary>
        /// 将镜头调整到指定设置参数
        /// </summary>
        /// <param name="to"></param>
        /// <param name="rootPos">相对坐标原点</param>
        /// <param name="completedAct"></param>
        public static void SetCameraTo(GameCameraSetting to, Vector3 rootPos, Action completedAct = null)
        {
            if (INSTANCE)
            {
                float duration = to.duration;

                if (duration < 0)
                    duration = 0f;

                if (to.Position.w > 0)
                {
                    INSTANCE.IsRouting = true;
                    INSTANCE.transform.DOLocalMove((Vector3)to.Position + rootPos, duration)
                        .SetEase(to.EaseType)
                        .onComplete = () =>
                        {
                            INSTANCE.IsRouting = false;
                            completedAct?.Invoke();
                        };
                }

                if (to.ViewAngle.w > 0)
                {
                    var torota = Quaternion.Euler(to.ViewAngle.x, to.ViewAngle.y, 0);
                    var tw = INSTANCE.MainCamera.transform.DOLocalRotateQuaternion(torota, duration).SetEase(to.EaseType);
                    //动画完成监听只做一次。
                    if (to.Position.w <= 0)
                    {
                        INSTANCE.IsRouting = true;
                        tw.onComplete = () =>
                        {
                            INSTANCE.IsRouting = false;
                            completedAct?.Invoke();
                        };
                    }
                }

                if (to.HighMin > 0 && to.HighMax > 0)
                {
                    INSTANCE.SetCameraHighRange(to.HighMin, to.HighMax);
                }

                if (completedAct != null)
                {
                    if (to.Position.w <= 0 && to.ViewAngle.w <= 0)
                    {
                        completedAct.Invoke();
                    }
                }
            }
        }

        public void OpenBlack()
        {
            _Black.SetActive(true);
        }

        public void CloseBlack()
        {
            _Black.SetActive(false);
        }



        /// <summary>
        /// 新增加得相机控制..使用 Setting控制相机..
        /// </summary>
        public CameraSetting DefaultSetting;


        public CameraSetting NowUsingSeting
        {
            get
            {
                _NowUsingSeting.Position = transform.position;
                _NowUsingSeting.Position.w = 1;
                return _NowUsingSeting;
            }
        }
        CameraSetting _NowUsingSeting;

        private void Start()
        {

            DefaultSetting = GetComponent<CameraSetting>();
            if (DefaultSetting != null)
                _UseSetting(DefaultSetting, false);
        }

        public CameraController Focus(GameObject who/*, CameraSetting NowCameraSetting*/)
        {
            if (who == null) return this;


            LookAt(who.transform);





            return this;
        }

        //public CameraController Focus(GameObject who, string CameraSettingKey = "default")
        //{

        //    if (who == null) return this;



        //    Focus(who);

        //    return this;
        //}

        public CameraController UseSetting(CameraSetting setting)
        {
            //
            _UseSetting(setting);

            return this;
        }
        void _UseSetting(CameraSetting setting, bool anim = true, GameObject focuswho = null)
        {
            if (setting == null)
                setting = DefaultSetting;

            _NowUsingSeting = setting;

            float H = setting.HighDefault > 0 ? setting.HighDefault : transform.position.y;

            // 目标旋转向量
            Quaternion QQ = setting.ViewAngle.w > 0 ? Quaternion.Euler(setting.ViewAngle.x, setting.ViewAngle.y, setting.ViewAngle.z) : MainCamera.transform.localRotation;
            // 获取 焦点
            Vector3 _focused = focuswho != null ? focuswho.transform.position + setting.FocusOffset : _Line_PANEL(MainCamera.transform.position, MainCamera.transform.forward, Vector3.up, Vector3.zero);
            //计算 相机位置.
            Vector3 tartgetpos = setting.Position.w > 0 ? setting.Position : _Line_PANEL(_focused, QQ * Vector3.back, Vector3.up, Vector3.up * H);



            // 响应相机得各类参数 设置..

            // 处理 包含相机旋转得...........
            if (setting.ViewAngle.w > 0)
            {

                if (anim)
                {
                    MainCamera.transform.DOLocalRotateQuaternion(QQ, setting.duration).SetEase(setting.EaseType);
                    transform.DOMove(tartgetpos, setting.duration).SetEase(setting.EaseType);
                }
                else
                {
                    MainCamera.transform.localRotation = Quaternion.Euler(setting.ViewAngle);
                    transform.position = tartgetpos;
                }

            }
            else //处理直接移动得..
            {

                if (anim)
                {
                    transform.DOMove(tartgetpos, setting.duration).SetEase(setting.EaseType);
                }
                else
                    transform.position = tartgetpos;

            }
        }

        private int GameCameraDefaultLayer;
        private LayerMask GameCameraDefaultPhysics;
        public void SetCameraLayer(LayerMask layerMask, LayerMask PhysicsLayerMask)
        {
            if (GameCamera != null && MainCamera != null)
            {
                GameCameraDefaultLayer = GameCamera.cullingMask;

                GameCamera.cullingMask = layerMask;

                if (GameCamera.GetComponent<PhysicsRaycaster>() != null)
                {
                    var pr = GameCamera.GetComponent<PhysicsRaycaster>();
                    GameCameraDefaultPhysics = pr.eventMask;
                    pr.eventMask = PhysicsLayerMask;
                }

                //WI相机
                //UniversalAdditionalCameraData ucd = MainCamera.GetUniversalAdditionalCameraData();

                //LayerMask WILayerMask = LayerMask.GetMask("WI");
                //if (ucd != null && ucd.cameraStack != null)
                //{
                //    foreach (var stackCamera in ucd.cameraStack)
                //    {
                //        if (stackCamera != null && stackCamera.gameObject != null)
                //        {
                //            if ((stackCamera.cullingMask & WILayerMask.value) > 0)//WI层
                //            {
                //                stackCamera.gameObject.SetActive(false);
                //            }
                //        }
                //    }
                //}
            }
        }

        public void ResetCameraLayer()
        {
            if (GameCamera != null && MainCamera != null)
            {
                GameCamera.cullingMask = GameCameraDefaultLayer;

                if (GameCamera.GetComponent<PhysicsRaycaster>() != null)
                {
                    GameCamera.GetComponent<PhysicsRaycaster>().eventMask = GameCameraDefaultPhysics;
                }

                //    //WI相机
                //    UniversalAdditionalCameraData ucd = MainCamera.GetUniversalAdditionalCameraData();

                //    LayerMask WILayerMask = LayerMask.GetMask("WI");
                //    if (ucd != null && ucd.cameraStack != null)
                //    {
                //        foreach (var stackCamera in ucd.cameraStack)
                //        {
                //            if (stackCamera != null && stackCamera.gameObject != null)
                //            {
                //                if ((stackCamera.cullingMask & WILayerMask.value) > 0)//WI层
                //                {
                //                    stackCamera.gameObject.SetActive(true);
                //                }
                //            }
                //        }
                //    }
            }
        }
        public delegate Vector3 Vector3Action();
        bool PostionSyncing = false;
        Vector3Action _OnPostionSync;
        public CameraController SetPostionSync(Vector3Action on)
        {
            PostionSyncing = true;
            _OnPostionSync = on;
            return this;
        }
        public CameraController SetPostionSync(bool sync)
        {
            PostionSyncing = sync;
            return this;
        }

    }
}

